package com.jrx.anytxn.param.utils;


import com.jrx.anytxn.param.dto.aviator.ConditionGroupReq;
import com.jrx.anytxn.param.enums.Match;
import com.jrx.anytxn.param.enums.OperateType;
import com.jrx.anytxn.param.enums.ValueType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;

import static com.jrx.anytxn.param.enums.OperateType.*;


/**
 * 表达式转换工具类
 *
 * @author yxy
 * Created by yxy on 2017/7/24.
 */
public class ConditionGroupUtils {


    private ConditionGroupUtils() {
    }

    private static final Logger logger = LoggerFactory.getLogger(ConditionGroupUtils.class);

    private static final String NAME = "custom.list";

    /**
     * 当前规则所用到的字段标识
     *
     * @param conditionNode
     * @param fields
     */
    public static void expressionField(ConditionGroupReq conditionNode, List<String> fields, List<String> valueTypes, List<String> defalutValues) {
        if (conditionNode.getNodeType() == 1) {
            if (!fields.contains(conditionNode.getFieldValueBid())) {
                String fieldBid = conditionNode.getFieldBid();
                fields.add(StringUtils.isEmpty(fieldBid) ? "" : fieldBid);

                String valueType = conditionNode.getValueType().name();
                valueTypes.add(StringUtils.isEmpty(valueType) ? "" : valueType);

                String defaultValue = conditionNode.getDefaultValue();
                defalutValues.add(StringUtils.isEmpty(defaultValue) ? "" : defaultValue);
            }

            if (!StringUtils.isEmpty(conditionNode.getFieldValueBid()) && !fields.contains(conditionNode.getFieldValueBid())) {
                String fieldBid = conditionNode.getFieldValueBid();
                fields.add(StringUtils.isEmpty(fieldBid) ? "" : fieldBid);

                String valueType = conditionNode.getValueFieldValueType().name();
                valueTypes.add(StringUtils.isEmpty(valueType) ? "" : valueType);

                String defaultValue = conditionNode.getValueFieldDefaultValue();
                defalutValues.add(StringUtils.isEmpty(defaultValue) ? "" : defaultValue);
            }
        } else if (conditionNode.getNodeType() == 2 && !CollectionUtils.isEmpty(conditionNode.getChildren())) {
            conditionNode.getChildren().forEach(node -> expressionField(node, fields, valueTypes, defalutValues));
        }
    }


    public static String nodeExpression(ConditionGroupReq conditionNode) {
        StringBuilder exp = new StringBuilder();
        if (conditionNode.getNodeType() == 1) {
            String f = conditionNode.getFieldBid();
            OperateType ot = conditionNode.getOperateType();

            if (conditionNode.getValueType() == ValueType.LISTS) {
                if (ot == EQ || ot == LT || ot == GT || ot == NEQ || ot == GE || ot == LE) {
                    exp.append(NAME).append("(").append(f).append(",").append(conditionNode.getListNum()).append(",").append("'").append(conditionNode.getListType() == Match.ANY ? "any" : "all").append("'").append(",").append("'").append(ot.getCode()).append("'").append(",").append(StringUtils.isEmpty(conditionNode.getFieldValueBid()) ? "'" + conditionNode.getValues().get(0) + "'" : conditionNode.getFieldValueBid()).append(")");
                }
            } else {
                if (ot == EQ || ot == LT || ot == GT || ot == NEQ || ot == GE || ot == LE) {
                    exp.append(f).append(ot.getCode());
                    if (!CollectionUtils.isEmpty(conditionNode.getValues())) {
                        exp.append(toValue(f, conditionNode.getValueType(), conditionNode.getValues().get(0)));
                    } else if (!StringUtils.isEmpty(conditionNode.getFieldValueBid())) {
                        exp.append(conditionNode.getFieldValueBid());
                    }
                } else if (ot == NULL) {
                    exp.append(f).append(EQ.getCode()).append("''");
                } else if (ot == In || ot == NOTIN || ot == LIKE || ot == NOTLIKE) {
                    exp.append(ot.getCode()).append("(").append(f).append(",");
                    if (!CollectionUtils.isEmpty(conditionNode.getValues())) {
                        exp.append(toValue(f, conditionNode.getValueType(), String.join(",", conditionNode.getValues())));
                    } else if (!StringUtils.isEmpty(conditionNode.getFieldValueBid())) {
                        exp.append(conditionNode.getFieldValueBid());
                    }
                    exp.append(")");
                } else if (ot == NONULL) {
                    exp.append(f).append(NEQ.getCode()).append("''");
                } else if (ot == HASVAL) {
                    exp.append(f).append(NEQ.getCode()).append("nil");
                } else if (ot == NOHASVAL) {
                    exp.append(f).append(EQ.getCode()).append("nil");
                } else if (ot == BETWEEN && !CollectionUtils.isEmpty(conditionNode.getValues())) {
                    //必须要有两个值
                    exp.append(f).append(GE.getCode()).append(toValue(f, conditionNode.getValueType(), conditionNode.getValues().get(0)));
                    if (conditionNode.getValues().size() >= 2) {
                        exp.append(" && ").append(f).append(LT.getCode()).append(toValue(f, conditionNode.getValueType(), conditionNode.getValues().get(1)));
                    }
                }
            }
        } else if (!CollectionUtils.isEmpty(conditionNode.getChildren())) {
            for (int i = 0; i < conditionNode.getChildren().size(); i++) {
                exp.append("(").append(nodeExpression(conditionNode.getChildren().get(i))).append(")");
                if (i < conditionNode.getChildren().size() - 1) {
                    exp.append(" ").
                            append(conditionNode.getMatch() == Match.ALL ? "&&" : "||").append(" ");
                }
            }
        }


        return exp.toString();
    }

    private static final String NUM_MATCH = "[\\d.]+";

    private static Object toValue(String bid, ValueType valueType, String val) {
        if (valueType == ValueType.CURRENCY || valueType == ValueType.DOUBLE || valueType == ValueType.INTEGER || valueType == ValueType.LONG || valueType == ValueType.TIMESTAMP) {
            if (StringUtils.isEmpty(val)) {
                return 0;
            }
            if (!val.matches(NUM_MATCH)) {
                logger.error(" {}为数值型字段, 比较值为非数字: {}", bid, val);
            }
            return val;
        } else if (valueType == ValueType.BOOLEAN) {
            if (StringUtils.isEmpty(val)) {
                return 0;
            }
            String t = "1";
            String t2 = "true";
            return val.equals(t) || val.equals(t2) ? 1 : 0;
        } else {
            if (StringUtils.isEmpty(val)) {
                return "''";
            }
            return "'" + val + "'";
        }
    }

}
